/**
 * Copyright (C) 2017 - 2020 https://github.com/joewee
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bifrost.service.impl;

import com.bifrost.constant.ShipmentMode;
import com.bifrost.constant.ShippingType;
import com.bifrost.constant.StoreShipmentTemplate;
import com.bifrost.entity.*;
import com.bifrost.exception.PricingException;
import com.bifrost.exception.UnsupportedShippingTypeException;
import com.bifrost.model.OrderRequest;
import com.bifrost.repository.*;
import com.bifrost.service.ProductSkuService;
import com.bifrost.service.ShippingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author joewee
 * @version 1.0.0
 * @Date 2017/11/22 17:50
 */
@Service
public class ShipingServiceImpl implements ShippingService {
    @Autowired
    SkuShipmentFreeRegionRepository skuShipmentFreeRegionRepository;
    @Autowired
    SkuShipmentRegionRepository skuShipmentRegionRepository;
    @Autowired
    SkuShipmentRepository skuShipmentRepository;
    @Autowired
    ProductSkuService skuService;
    @Autowired
    MerchantShipmentRepository merchantShipmentRepository;
    @Autowired
    MerchantShipmentRegionRepository merchantShipmentRegionRepository;
    @Autowired
    ProductSkuRepository productSkuRepository;

    @Override
    public boolean canDelivery(OrderRequest request) {
        return true;
    }

    /**
     * 计算商品单品邮费
     *
     * @param order
     * @return
     */
    @Override
    public BigDecimal shippingPricingBySkuTemplate(Order order, CountryArea district) throws PricingException {
        List<OrderItem> items = order.getOrderItems();
        BigDecimal totalShippingFee = shippingPricingBySkuTemplate(items, district);
        return totalShippingFee;
    }

    /**
     * 按照店铺运费模式计算邮费
     *
     * @param store
     * @param order
     * @return
     */
    @Override
    public BigDecimal shippingPricingByStoreTemplate(MerchantStore store, Order order) throws PricingException {
        CountryArea deliveryDistrict = order.getDeliveryDistrict();
        //店铺模式
        if (ShipmentMode.STORE.equalsIgnoreCase(store.getShipmentMode())) {
            List<MerchantShipment> storestemplate = merchantShipmentRepository.findAllByMerchantStore(store);
            if (storestemplate == null || storestemplate.isEmpty()) {
                throw new PricingException("店铺运费模板未设置");
            }
            MerchantShipmentRegion region = merchantShipmentRegionRepository.findFirstByShipmentDistrictAndMerchantShipmentIn(deliveryDistrict, storestemplate);
            if (region == null) {
                throw new PricingException("该区域店铺不提供快递服务");
            }
            MerchantShipment template = region.getMerchantShipment();
            //固定模式
            if (StoreShipmentTemplate.FIXED.equalsIgnoreCase(template.getType())) {
                BigDecimal shipmentFee = template.getDefaultShipmentFee();
                return shipmentFee == null ? BigDecimal.ZERO : shipmentFee;
            } else {
                //运费按照商品金额计算
                if (order.getSubTotal().compareTo(template.getRequiredAmount()) >= 0) {
                    return BigDecimal.ZERO;
                } else {
                    return template.getDefaultShipmentFee();
                }
            }
        }
        throw new PricingException("订单不适用于店铺运费模式");
    }

    /**
     * 混合模式下计算邮费
     *
     * @param order
     * @param deliveryDistrict
     * @return
     */
    @Override
    public BigDecimal shippingPricingByMixedTemplate(Order order, CountryArea deliveryDistrict) throws PricingException {
        /**
         * 筛选单品优先
         * 将非单品优先按照店铺-单品的顺序计算邮费
         * */
        List<OrderItem> items = order.getOrderItems();
        Map<Boolean, List<OrderItem>> map = items.stream().collect(Collectors.groupingBy(orderItem -> {
            SkuShipment skuShipment = productSkuRepository.findOne(orderItem.getSkuId()).getShipmentTemplate();
            if (skuShipment == null) {
                return Boolean.FALSE;
            }
            return skuShipment.getPriorityHigh();
        }));
        Iterator<Map.Entry<Boolean, List<OrderItem>>> iterator = map.entrySet().iterator();
        BigDecimal total = BigDecimal.ZERO;
        while (iterator.hasNext()) {
            Map.Entry<Boolean, List<OrderItem>> entry = iterator.next();
            Boolean isPriority = entry.getKey();
            //单品优先
            if (Boolean.TRUE.equals(isPriority)) {
                List<OrderItem> orderItems = entry.getValue();
                total = total.add(shippingPricingBySkuTemplate(orderItems, deliveryDistrict));
            } else {
                //非单品优先的查询是否满足店铺免邮
                CountryArea district = order.getDeliveryDistrict();
                List<MerchantShipment> storestemplate = merchantShipmentRepository.findAllByMerchantStore(order.getMerchantStore());
                if (storestemplate != null && !storestemplate.isEmpty()) {
                    MerchantShipmentRegion region = merchantShipmentRegionRepository.findFirstByShipmentDistrictAndMerchantShipmentIn(deliveryDistrict, storestemplate);
                    if (region != null) {
                        MerchantShipment template = region.getMerchantShipment();
                        BigDecimal shipmentFee = template.getDefaultShipmentFee()==null?BigDecimal.ZERO:template.getDefaultShipmentFee();
                        //固定模式
                        if (StoreShipmentTemplate.FIXED.equalsIgnoreCase(template.getType())) {
                            //BigDecimal shipmentFee = template.getDefaultShipmentFee();
                            //total=total.add(shipmentFee==null?BigDecimal.ZERO:shipmentFee);
                            //运费按照商品金额计算，不满足包邮则按单品计算
                            //if(total.compareTo(BigDecimal.ZERO)<0){
                            List<OrderItem> orderItems = entry.getValue();
                            //total = total.add(shippingPricingBySkuTemplate(orderItems, district));  错误？：还是按照sku模板进行运算
                            total = total.add(shipmentFee);
                            //}
                        } else {
                            List<OrderItem> orderItems = entry.getValue();
                            BigDecimal subTotal = orderItems.stream().map(item -> {
                                return item.getSkuPrice().multiply(BigDecimal.valueOf(item.getSkuQuantity()));
                            }).reduce(BigDecimal::add).get();
                            //运费按照商品金额计算，不满足包邮则按单品计算
                            if (subTotal.compareTo(template.getRequiredAmount()) < 0) {
                                //total = total.add(shippingPricingBySkuTemplate(orderItems, district));  错误？：还是按照sku模板进行运算
                                total = total.add(shipmentFee);
                            }
                        }
                    }
                }
            }
        }
        //order.setTotalShippingFee(total);
        return total;
    }

    protected BigDecimal shippingPricingBySkuTemplate(List<OrderItem> items, CountryArea deliveryDistrict) throws PricingException {
        //筛选定义了单品运费模板的行项目
        List<OrderItem> matchedItems = items.stream().filter(orderItem -> {
            return productSkuRepository.findOne(orderItem.getSkuId()).getShipmentTemplate() != null;
        }).collect(Collectors.toList());
        if (matchedItems == null || matchedItems.isEmpty()) {
            return BigDecimal.ZERO;
        }
        Map<Long, List<OrderItem>> map = matchedItems.stream().collect(Collectors.groupingBy(orderItem -> {
            SkuShipment template = productSkuRepository.findOne(orderItem.getSkuId()).getShipmentTemplate();
            return template.getSkuShipmentId();
        }));
        Iterator<Map.Entry<Long, List<OrderItem>>> iterator = map.entrySet().iterator();
        List<BigDecimal> shippingList = new ArrayList<>(map.size());
        while (iterator.hasNext()) {
            Map.Entry<Long, List<OrderItem>> entry = iterator.next();
            List<OrderItem> items1 = entry.getValue();
            BigDecimal total = shippingPricingBySkuTemplate(entry.getKey(), items1, deliveryDistrict);
            shippingList.add(total);
        }
        //一单多个运费模板时取最大值
        BigDecimal totalShippingFee = shippingList.stream().max(new Comparator<BigDecimal>() {
            @Override
            public int compare(BigDecimal o1, BigDecimal o2) {
                return o1.compareTo(o2);
            }
        }).get();
        return totalShippingFee;
    }

    /**
     * 寻找最合适的快递方式
     *
     * @param shippingTypes
     * @return
     */
    @Override
    public String findBestShippingType(List<String> shippingTypes) throws UnsupportedShippingTypeException {
        if (shippingTypes.contains(ShippingType.DELIVERY) && shippingTypes.contains(ShippingType.SELF_DELIVERY)) {
            throw new UnsupportedShippingTypeException("订单存在不兼容快递类型");
        } else if (shippingTypes.contains(ShippingType.DELIVERY)) {
            return ShippingType.DELIVERY;
        } else if (shippingTypes.contains(ShippingType.SELF_DELIVERY)) {
            return ShippingType.SELF_DELIVERY;
        } else {
            return ShippingType.BOTH;
        }
    }

    protected BigDecimal shippingPricingBySkuTemplate(Long skuTemplate, List<OrderItem> items, CountryArea deliveryDistrict) throws PricingException {
        SkuShipment template = skuShipmentRepository.findOne(skuTemplate);
        if (template != null) {
            if (Boolean.TRUE.equals(template.isFree())) {
                return BigDecimal.ZERO;
            }
            SkuShipmentFreeRegion region = skuShipmentFreeRegionRepository.findFirstBySkuShipmentAndShipmentDistrict(template, deliveryDistrict);
            //免邮区域
            if (region != null) {
                return BigDecimal.ZERO;
            }
            BigDecimal weight = BigDecimal.ZERO;
            for (OrderItem item : items) {
                ProductSku sku = skuService.getSkuById(item.getSkuId());
                weight = weight.add(sku.getSkuWeight().multiply(BigDecimal.valueOf(item.getSkuQuantity())));
            }
            SkuShipmentRegion skuShipmentRegion = skuShipmentRegionRepository.findFirstBySkuShipmentAndShipmentDistrict(template, deliveryDistrict);
            if (skuShipmentRegion == null) {
                /**
                 * 未配置区域则取模板默认值
                 * */
                return pricing(weight, template.getFirstRange(), template.getFirstPrice(), template.getAdditional(), template.getAdditionalPrice());
            } else {
                return pricing(weight, skuShipmentRegion.getFirstRange(), skuShipmentRegion.getFirstPrice(), skuShipmentRegion.getAdditional(), skuShipmentRegion.getAdditionalPrice());
            }

        }
        throw new PricingException("没有找到相应的运费模板：" + template.getSkuShipmentId());
    }

    protected BigDecimal pricing(BigDecimal weight, BigDecimal firstWeight, BigDecimal firstFee, BigDecimal additionalWeight, BigDecimal additionalFee) {
        if (weight.compareTo(firstWeight) <= 0) {
            return firstFee;
        }
        //向上取整
        return weight.subtract(firstWeight).setScale(0, BigDecimal.ROUND_UP).divide(additionalWeight).multiply(additionalFee).add(firstFee);
    }
}
